.section .text
.globl _start

_start:
	mov	$0x10,	%ax
	mov	%ax,	%ds
	mov	%ax,	%es
	mov	%ax,	%fs
	mov	%ax,	%ss
	mov	$0x7E00,	%esp

//=======   加载gdt表
//TODO 可能有问题，等跑起来看看再说
	lgdt GDT_POINTER(%rip)

//=======  加载ldt表
//TODO 可能有问题，等跑起来看看再说
	lidt IDT_POINTER(%rip)
    
    mov $0x10,%ax
    mov %ax,%ds
    mov %ax,%es
    mov %ax,%fs
    mov %ax,%gs
    mov %ax,%ss
    mov $0x7E00,%esp

//载入页表
    movq $0x101000,%rax
    movq %rax,%cr3
	movq switch_seg(%rip),%rax
    pushq $0x08 //段选择子
	pushq %rax
	lretq

switch_seg:
	.quad	entry64

entry64:
	movq	$0x10,%rax
	movq	%rax,%ds
	movq	%rax,%es
	movq	%rax,%gs
	movq	%rax,%ss
	movq 	$0xffff800000007E00,%rsp

//中断门描述符结构详解
//在x86-64架构中，中断门描述符采用16字节格式，具体结构如下：

//低8字节（0-63位）：‌

//0-15位‌：中断处理程序代码段偏移量的低16位
//16-31位‌：目标代码段选择子
//32-39位‌：保留位（通常为0）
//40-43位‌：类型字段（0b1110表示32位中断门）
//44位‌：描述符权限级别（DPL）
//45-46位‌：存储段标志（始终为1）
//47位‌：存在位（P）
//48-63位‌：中断处理程序代码段偏移量的高16位
//高8字节（64-127位）：‌

//64-95位‌：中断处理程序代码段偏移量的最高32位
//96-127位‌：保留位（必须为0）
setup_idt:
	leaq 	ignore_int(%rip),%rdx
	movq 	$(0x08 << 16),%rax	//选择子为8
	movw 	%dx,%ax				//将偏移的0-15位赋给rax的0-15位
	movq	$(0x8E00 << 32),%rcx	//8E --> 10001110b -> 47位为1(为0表示屏蔽此中断，反之则启用此中断),40-43位为E(表示中断门)
	addq	%rcx,%rax	//将上一步40-47位获取的标志赋到rax相应的位置
	movl	%edx,%ecx
	shrl	$16,%ecx
	shlq	$48,%rcx	//获取偏移的16-31位
	addq 	%rcx,%rax

	shrq	$32,%rdx	//取偏移的高32位
	leaq	IDT_Table(%rip),%rdi //这里可以将rdi换成别的寄存器
	mov 	$256,%rcx	//中断表有256个项
rp_sidt:
	movq	%rax,(%rdi)	//存放低8字节
	movq	%rdx,8(%rdi)	//存放高8字节
	addq	$0x10,%rdi
	decq	%rcx
	loop	rp_sidt	


	mov go_to_kernel(%rip),%rax
    pushq $0x08 
	pushq %rax
	lretq

go_to_kernel:
//这个Start_Kernel对应的是main.c 实际上是把main.c里面的Start_Kernel函数当做入口
	.quad	Start_Kernel
//这里留下了一个问题，为什么书上将ds,es定为0x10
ignore_int:
	//因为不清楚中断会改变什么,所以，将所有寄存器现场全部保存
	cld
	pushq %rax
	pushq %rbx
	pushq %rcx
	pushq %rdx
	pushq %rbp
	pushq %rsi
	pushq %rdi
	pushq %r8
	pushq %r9
	pushq %r10
	pushq %r11
	pushq %r12
	pushq %r13
	pushq %r14
	pushq %r15
	movq %ds,%rax
	pushq %rax
	movq %es,%rax
	pushq %rax
//以上是保存寄存器操作

	movq $0x10,%rax
	movq %rax,%ds
	movq %rax,%es
// 	linux64位汇编 前6个参数通过寄存器传参 rdi,rsi,rdx,rcx,r8,r9	
	leaq int_msg(%rip),%rdx //字符串=int_msg
	movq $0x00000000,%rsi //背景色=黑色
	movq $0x00FF0000,%rdi //前景色为红色
	callq color_printk 

//以下是还原寄存器操作
	popq %rax
	mov %rax,%es
	popq %rax
	mov %rax,%es
	popq %r15
	popq %r14
	popq %r13
	popq %r12	
	popq %r11
	popq %r10
	popq %r9
	popq %r8
	popq %rdi
	popq %rsi
	popq %rbp
	popq %rdx
	popq %rcx
	popq %rbx
	popq %rax
//因为这是一个中断例程，所以，必须要用iret
	iretq
int_msg:
	.asciz "Unknown interrupt or fault at RIP\n"
//=======	初始化页表
.align 8 //将对齐标准设置为8个字节
//固定页表位置 0x100000 + 0x1000 = 0x101000
.org	0x1000

__PML4E:

	.quad	0x102007
	.fill	255,8,0
	.quad	0x102007
	.fill	255,8,0

.org	0x2000

__PDPTE:
	
	.quad	0x103003
	.fill	511,8,0

.org	0x3000

__PDE:

	.quad	0x000083	
	.quad	0x200083
	.quad	0x400083
	.quad	0x600083
	.quad	0x800083
	.quad	0xe0000083		/*0x a00000*/
	.quad	0xe0200083
	.quad	0xe0400083
	.quad	0xe0600083
	.quad	0xe0800083		/*0x1000000*/
	.quad	0xe0a00083
	.quad	0xe0c00083
	.quad	0xe0e00083
	.fill	499,8,0

//=======	GDT_Table

.section .data

.globl GDT_Table

GDT_Table:
	.quad	0x0000000000000000			/*0	NULL descriptor		       	00*/
	.quad	0x0020980000000000			/*1	KERNEL	Code	64-bit	Segment	08*/
	.quad	0x0000920000000000			/*2	KERNEL	Data	64-bit	Segment	10*/
	.quad	0x0020f80000000000			/*3	USER	Code	64-bit	Segment	18*/
	.quad	0x0000f20000000000			/*4	USER	Data	64-bit	Segment	20*/
	.quad	0x00cf9a000000ffff			/*5	KERNEL	Code	32-bit	Segment	28*/
	.quad	0x00cf92000000ffff			/*6	KERNEL	Data	32-bit	Segment	30*/
	.fill	10,8,0					/*8 ~ 9	TSS (jmp one segment <7>) in long-mode 128-bit 40*/
GDT_END:

GDT_POINTER:
GDT_LIMIT:	.word	GDT_END - GDT_Table - 1
GDT_BASE:	.quad	GDT_Table

//=======	IDT_Table
//======中断表有256个项，每项16个字节
.globl IDT_Table

IDT_Table:
	.fill  512,8,0
IDT_END:

IDT_POINTER:
IDT_LIMIT:	.word	IDT_END - IDT_Table - 1
IDT_BASE:	.quad	IDT_Table

//=======	TSS64_Table 
//save task state info

.globl	TSS64_Table

TSS64_Table:
	.fill  13,8,0
TSS64_END:

TSS64_POINTER:
TSS64_LIMIT:	.word	TSS64_END - TSS64_Table - 1
TSS64_BASE:	.quad	TSS64_Table